package com.rinoiot.weather.service.impl;

import com.alibaba.fastjson.JSON;
import com.rinoiot.weather.entity.Vo.CurrentWeatherVo;
import com.rinoiot.weather.entity.WeatherBitEntity;
import com.rinoiot.weather.entity.query.WeatherQueryParam;
import com.rinoiot.weather.service.CurrentWeatherService;
import com.rinoiot.weather.utils.GeoUtil;
import com.rinoiot.weather.utils.HttpsUtils;
import com.rinoiot.weather.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

@Slf4j
@Service
@ConditionalOnProperty(prefix = "weather", name = "dataSource", havingValue = "BIT")
public class BitWeatherServiceImpl implements CurrentWeatherService {

    private static final String WEATHER_BIT = "weatherBit";

    private final RedisUtil redisUtil;

    private final GeoUtil geoUtil;

    @Value("${weatherBit.key}")
    private String key;

    private static final String BASE_URL = "https://api.weatherbit.io/v2.0/current";

    public BitWeatherServiceImpl(RedisUtil redisUtil, GeoUtil geoUtil) {
        this.redisUtil = redisUtil;
        this.geoUtil = geoUtil;
    }

    @Override
    public CurrentWeatherVo getCurrentWeather(WeatherQueryParam param) {

        CurrentWeatherVo currentWeatherVo;
        // 从redis中获取
        Object weather = null;
        try {
            if (!ObjectUtils.isEmpty(param.getCityName())) {
                param.setCityName(param.getCityName().toLowerCase());
                weather = redisUtil.get(param.getCityName());
            }

            if (!StringUtils.isEmpty(param.getLat()) && !StringUtils.isEmpty(param.getLon())) {
                GeoResults<RedisGeoCommands.GeoLocation<String>> pointRadius =
                        geoUtil.getPointRadius(WEATHER_BIT, param.getLon(), param.getLat(), 5);
                if (!ObjectUtils.isEmpty(pointRadius) && !CollectionUtils.isEmpty(pointRadius.getContent())) {
                    String name = pointRadius.getContent().get(0).getContent().getName();
                    weather = redisUtil.get(name);
                }
            }
        } catch (Exception e) {
            log.warn("");
        }


        if (ObjectUtils.isEmpty(weather)) {
            // redis 中没有 请求获取数据
            currentWeatherVo = getCurrentWeatherVo(param);
        } else {
            currentWeatherVo = JSON.parseObject((String) weather, CurrentWeatherVo.class);
            // 时间间隔小于30分钟 重新获取
            if (System.currentTimeMillis() - currentWeatherVo.getCreateTime() > 30 * 60 * 1000) {
                currentWeatherVo = getCurrentWeatherVo(param);
            }
        }

        return currentWeatherVo;
    }

    // 向weatherBit发送请求获取天气数据
    private CurrentWeatherVo getCurrentWeatherVo(WeatherQueryParam param) {
        StringBuilder url = new StringBuilder(BASE_URL);

        if (!StringUtils.isEmpty(param.getCityName())) {
            url.append("?").append("city=").append(param.getCityName());
        } else {
            url.append("?").append("lat=").append(param.getLat())
                    .append("&lon=").append(param.getLon());
        }

        url.append("&key=").append(key);
        String get = HttpsUtils.Get(url.toString());
//        log.info(get);
        WeatherBitEntity weatherBitEntity = JSON.parseObject(get, WeatherBitEntity.class);
        CurrentWeatherVo trans = weatherBitEntity.trans();
        try {
            redisUtil.set(weatherBitEntity.getData().get(0).getCity_name().toLowerCase(),JSON.toJSONString(trans));
            geoUtil.geoAdd(WEATHER_BIT, weatherBitEntity.getData().get(0).getLon(),
                    weatherBitEntity.getData().get(0).getLat(),
                    weatherBitEntity.getData().get(0).getCity_name().toLowerCase());
        } catch (Exception e) {
            log.warn("redis 写入异常");
        }

        return trans;
    }
}
